using System;
using System.Collections.Generic;
using System.Text;

// 观察者接口
public interface IObserver
{
    void Update(WeatherData data);
}

// 主题接口
public interface ISubject
{
    void RegisterObserver(IObserver observer);
    void RemoveObserver(IObserver observer);
    void NotifyObservers();
}

// 气象数据类，用于传递气象信息
public class WeatherData
{
    public DateTime LastUpdateTime { get; set; }
    public double Temperature { get; set; }
    public double Humidity { get; set; }
    public double Pressure { get; set; }
    public string WeatherCondition { get; set; } // 天气状况

    public override string ToString()
    {
        return $"时间: {LastUpdateTime}, 温度: {Temperature}°C, 湿度: {Humidity}%, 气压: {Pressure}hPa, 天气: {WeatherCondition}";
    }
}

// 气象站类 - 主题类
public class WeatherStation : ISubject
{
    private List<IObserver> observers; // 观察者列表
    private WeatherData weatherData;   // 当前气象数据

    // 属性
    public DateTime LastUpdateTime
    {
        get { return weatherData.LastUpdateTime; }
    }

    public double Temperature
    {
        get { return weatherData.Temperature; }
        set
        {
            if (weatherData.Temperature != value)
            {
                weatherData.Temperature = value;
                UpdateData(); // 数据更新后通知观察者
            }
        }
    }

    public double Humidity
    {
        get { return weatherData.Humidity; }
        set
        {
            if (weatherData.Humidity != value)
            {
                weatherData.Humidity = value;
                UpdateData(); // 数据更新后通知观察者
            }
        }
    }

    public double Pressure
    {
        get { return weatherData.Pressure; }
        set
        {
            if (weatherData.Pressure != value)
            {
                weatherData.Pressure = value;
                UpdateData(); // 数据更新后通知观察者
            }
        }
    }

    public string WeatherCondition
    {
        get { return weatherData.WeatherCondition; }
        set
        {
            if (weatherData.WeatherCondition != value)
            {
                weatherData.WeatherCondition = value;
                UpdateData(); // 数据更新后通知观察者
            }
        }
    }

    // 构造函数
    public WeatherStation()
    {
        observers = new List<IObserver>();
        weatherData = new WeatherData
        {
            LastUpdateTime = DateTime.Now,
            Temperature = 0,
            Humidity = 0,
            Pressure = 0,
            WeatherCondition = "未知"
        };
    }

    // 注册观察者
    public void RegisterObserver(IObserver observer)
    {
        if (!observers.Contains(observer))
        {
            observers.Add(observer);
            // 立即向新注册的观察者发送当前数据
            observer.Update(new WeatherData(weatherData));
        }
    }

    // 移除观察者
    public void RemoveObserver(IObserver observer)
    {
        if (observers.Contains(observer))
        {
            observers.Remove(observer);
        }
    }

    // 通知所有观察者
    public void NotifyObservers()
    {
        // 创建数据副本，避免在通知过程中数据被修改
        WeatherData dataCopy = new WeatherData(weatherData);
        
        foreach (IObserver observer in observers)
        {
            observer.Update(dataCopy);
        }
    }

    // 更新数据并通知观察者
    private void UpdateData()
    {
        weatherData.LastUpdateTime = DateTime.Now;
        NotifyObservers();
    }

    // 设置所有气象数据
    public void SetMeasurements(double temperature, double humidity, double pressure, string weatherCondition)
    {
        bool dataChanged = false;
        
        if (weatherData.Temperature != temperature)
        {
            weatherData.Temperature = temperature;
            dataChanged = true;
        }
        
        if (weatherData.Humidity != humidity)
        {
            weatherData.Humidity = humidity;
            dataChanged = true;
        }
        
        if (weatherData.Pressure != pressure)
        {
            weatherData.Pressure = pressure;
            dataChanged = true;
        }
        
        if (weatherData.WeatherCondition != weatherCondition)
        {
            weatherData.WeatherCondition = weatherCondition;
            dataChanged = true;
        }
        
        if (dataChanged)
        {
            UpdateData();
        }
    }

    // 模拟获取新数据
    public void SimulateNewData()
    {
        Random random = new Random();
        double newTemp = Math.Round(20 + random.NextDouble() * 10 - 5, 1); // 15-25°C
        double newHumidity = Math.Round(40 + random.NextDouble() * 40, 1); // 40-80%
        double newPressure = Math.Round(990 + random.NextDouble() * 20, 1); // 990-1010hPa
        
        string[] conditions = { "晴天", "多云", "阴天", "小雨", "中雨", "大雨", "雷阵雨" };
        string newCondition = conditions[random.Next(conditions.Length)];
        
        Console.WriteLine($"\n气象站采集到新数据: 温度={newTemp}°C, 湿度={newHumidity}%, 气压={newPressure}hPa, 天气={newCondition}");
        SetMeasurements(newTemp, newHumidity, newPressure, newCondition);
    }
}

// 屏幕显示类 - 观察者
public class ScreenDisplay : IObserver
{
    private string displayName;
    private WeatherData lastWeatherData;

    public ScreenDisplay(string name)
    {
        displayName = name;
        lastWeatherData = null;
    }

    public void Update(WeatherData data)
    {
        lastWeatherData = data;
        Display();
    }

    public void Display()
    {
        if (lastWeatherData != null)
        {
            Console.WriteLine($"\n[{displayName}] 更新气象数据:");
            Console.WriteLine("====================================");
            Console.WriteLine($"更新时间: {lastWeatherData.LastUpdateTime.ToString("yyyy-MM-dd HH:mm:ss")}");
            Console.WriteLine($"温度:     {lastWeatherData.Temperature}°C");
            Console.WriteLine($"湿度:     {lastWeatherData.Humidity}%");
            Console.WriteLine($"气压:     {lastWeatherData.Pressure}hPa");
            Console.WriteLine($"天气状况: {lastWeatherData.WeatherCondition}");
            
            // 添加一些额外的显示信息
            string tempStatus = GetTemperatureStatus(lastWeatherData.Temperature);
            string humidityStatus = GetHumidityStatus(lastWeatherData.Humidity);
            
            Console.WriteLine($"\n温馨提示:");
            Console.WriteLine($"- 温度{tempStatus}");
            Console.WriteLine($"- 湿度{humidityStatus}");
            Console.WriteLine("====================================");
        }
    }

    private string GetTemperatureStatus(double temp)
    {
        if (temp < 10)
            return "较低，请注意保暖";
        else if (temp < 20)
            return "适宜，体感舒适";
        else if (temp < 30)
            return "较高，请注意防暑";
        else
            return "很高，建议减少户外活动";
    }

    private string GetHumidityStatus(double humidity)
    {
        if (humidity < 30)
            return "较低，空气干燥";
        else if (humidity < 60)
            return "适宜，体感舒适";
        else if (humidity < 80)
            return "较高，空气湿润";
        else
            return "很高，注意防潮";
    }
}

// 数据库保存类 - 观察者
public class DatabaseSaver : IObserver
{
    private string databaseName;
    private List<WeatherData> weatherHistory; // 用于模拟数据库存储

    public DatabaseSaver(string name)
    {
        databaseName = name;
        weatherHistory = new List<WeatherData>();
    }

    public void Update(WeatherData data)
    {
        SaveToDatabase(data);
    }

    public void SaveToDatabase(WeatherData data)
    {
        // 模拟保存到数据库的操作
        weatherHistory.Add(new WeatherData(data));
        
        Console.WriteLine($"\n[{databaseName}] 保存数据到数据库:");
        Console.WriteLine("------------------------------------");
        Console.WriteLine($"保存时间: {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
        Console.WriteLine($"数据内容: {data}");
        Console.WriteLine($"数据库中总记录数: {weatherHistory.Count}");
        Console.WriteLine("------------------------------------");
    }

    // 获取历史记录数量
    public int GetRecordCount()
    {
        return weatherHistory.Count;
    }

    // 导出最近的记录
    public void ExportRecentRecords(int count)
    {
        Console.WriteLine($"\n[{databaseName}] 导出最近 {count} 条记录:");
        Console.WriteLine("====================================");
        
        int recordsToShow = Math.Min(count, weatherHistory.Count);
        for (int i = weatherHistory.Count - recordsToShow; i < weatherHistory.Count; i++)
        {
            Console.WriteLine($"[{i + 1}] {weatherHistory[i]}");
        }
        
        Console.WriteLine("====================================");
    }
}

// 主程序类
class Program
{
    static void Main(string[] args)
    {
        // 创建气象站
        WeatherStation weatherStation = new WeatherStation();

        // 创建观察者
        ScreenDisplay mainScreen = new ScreenDisplay("主屏幕显示器");
        ScreenDisplay mobileScreen = new ScreenDisplay("移动设备显示器");
        DatabaseSaver localDB = new DatabaseSaver("本地数据库");
        DatabaseSaver cloudDB = new DatabaseSaver("云端数据库");

        // 注册观察者
        Console.WriteLine("=== 注册观察者 ===");
        weatherStation.RegisterObserver(mainScreen);
        weatherStation.RegisterObserver(localDB);

        // 模拟气象数据变化
        Console.WriteLine("\n=== 模拟气象数据变化 ===");
        weatherStation.SimulateNewData();
        
        // 添加新的观察者
        Console.WriteLine("\n=== 添加新的观察者 ===");
        weatherStation.RegisterObserver(mobileScreen);
        weatherStation.RegisterObserver(cloudDB);

        // 再次模拟数据变化
        Console.WriteLine("\n=== 再次模拟气象数据变化 ===");
        weatherStation.SimulateNewData();
        
        // 通过属性单独修改数据
        Console.WriteLine("\n=== 通过属性单独修改温度数据 ===");
        weatherStation.Temperature = 30.5;
        
        // 移除一个观察者
        Console.WriteLine("\n=== 移除本地数据库观察者 ===");
        weatherStation.RemoveObserver(localDB);
        
        // 再次模拟数据变化
        Console.WriteLine("\n=== 第三次模拟气象数据变化 ===");
        weatherStation.SimulateNewData();
        
        // 导出云端数据库的记录
        Console.WriteLine("\n=== 导出云端数据库的历史记录 ===");
        cloudDB.ExportRecentRecords(3);
        
        // 演示通过设置多个参数来更新数据
        Console.WriteLine("\n=== 手动设置特定气象数据 ===");
        weatherStation.SetMeasurements(22.5, 65.0, 1005.2, "晴天");

        Console.WriteLine("\n气象站演示完成！按任意键退出...");
        Console.ReadKey();
    }
}

// 扩展WeatherData类，添加复制构造函数
public partial class WeatherData
{
    public WeatherData(WeatherData source)
    {
        LastUpdateTime = source.LastUpdateTime;
        Temperature = source.Temperature;
        Humidity = source.Humidity;
        Pressure = source.Pressure;
        WeatherCondition = source.WeatherCondition;
    }
}